namespace Viyi.Util.Extensions.Convert;

public static class ObjectToStructExtensions {
    /// <summary>
    /// 将object对象当作指定数据类型进行处理。
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="object">源数据</param>
    /// <param name="defaultValue">缺省值</param>
    /// <returns>返回转换引用类型之后的值，如果不能转换为指定引用类型，
    /// 返回<c>defaultValue</c></returns>
    /// <remarks>与as关键字的区别在于，<c>As</c>方法可以处理结构。</remarks>
    public static T As<T>(this object @object, T defaultValue) where T : struct {
        try { return (T) @object; }
        catch { return defaultValue; }
    }

    /// <summary>
    /// 将object对象当作指定数据类型进行处理。
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="object">源数据</param>
    /// <returns>返回转换引用类型之后的值，如果不能转换为指定引用类型，
    /// 返回<c>default(T)</c></returns>
    /// <remarks>与as关键字的区别在于，<c>As</c>方法可以处理结构。</remarks>
    public static T As<T>(this object @object)
        where T : struct {
        return @object.As(default(T));
    }

    /// <summary>
    /// 将object对象转换为指定数据类型。
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="object">源数据</param>
    /// <param name="defaultValue">缺省值</param>
    /// <returns>通过<c>System.Convert</c>将源数据转换为指定类型的数据，
    /// 如果转换不成功，返回<c>defaultValue</c></returns>
    public static T ConvertTo<T>(object @object, T defaultValue) where T : struct {
        try { return (T) System.Convert.ChangeType(@object, typeof(T)); }
        catch { return defaultValue; }
    }

    /// <summary>
    /// 将object对象转换为指定数据类型。
    /// </summary>
    /// <typeparam name="T">目标类型</typeparam>
    /// <param name="object">源数据</param>
    /// <returns>通过<c>System.Convert</c>将源数据转换为指定类型的数据，
    /// 如果转换不成功，返回<c>default(T)</c></returns>
    public static T ConvertTo<T>(object @object) where T : struct {
        return ConvertTo<T>(@object, default(T));
    }
}
